using System.Collections;
using System.Collections.Generic;
using Testbed.Abstractions;
using UnityEngine;
using cframework.lockstep;
using Unity.VisualScripting;
using System.Linq;

public class TestLockStepBehaviour : LockStepBehaviour
{
    class KeyInfo
    {
        public KeyCode key;
        public System.Action callback;
    }

    KeyCode key;
    Dictionary<KeyCode, System.Action> keyInfos = new Dictionary<KeyCode, System.Action>();

    bool printedUpdate;
    bool printedLateUpdate;

    protected override void Awake()
    {
        base.Awake();

        keyInfos.Add(KeyCode.Alpha1, () =>
            {
                Debug.Log("test timer: " + LockStepWorld.current.time);
                this.StartTimer_LS(() =>
                {
                    Debug.Log("timer callback time: " + LockStepWorld.current.time);
                    return true; //return true to continue timer
                }, 1, 2);
            }
        );

        keyInfos.Add(KeyCode.Alpha2, () =>
            {
                Debug.Log("test timer result: " + LockStepWorld.current.time);
                this.StartTimer_LS(() =>
                {
                    Debug.Log("timer callback only called once: " + LockStepWorld.current.time);
                    return false; //return false to stop timer
                }, 1, 10);
            }
        );

        keyInfos.Add(KeyCode.Alpha3, () =>
            {
                IEnumerator TestCoroutine_LS()
                {
                    Debug.Log("before yield return null: " + LockStepWorld.current.time + " | " + LockStepWorld.current.deltaTime);
                    yield return null;
                    Debug.Log("before WaitForSecond_LS(1):  " + LockStepWorld.current.time + " | " + LockStepWorld.current.deltaTime);
                    yield return new WaitForSecond_LS(1);
                    Debug.Log("after WaitForSecond_LS(1):  " + LockStepWorld.current.time + " | " + LockStepWorld.current.deltaTime);
                }

                Debug.Log("test behaviour coroutine: " + LockStepWorld.current.time);
                this.StartCoroutine_LS(TestCoroutine_LS());
            }
        );

        keyInfos.Add(KeyCode.Alpha4, () =>
        {
            IEnumerator TestCoroutine_LS_WithResult()
            {
                {
                    var e = ResultCoroutine().WithResult();
                    yield return e;
                    Debug.Log("ResultCoroutine return result: " + e.Current);
                }
            }

            IEnumerator ResultCoroutine()
            {
                {
                    var e = ResultCoroutine2().WithResult();
                    yield return e;
                    Debug.Log("ResultCoroutine2 return result: " + e.Current);
                }

                yield return "this is a result string";
            }

            IEnumerator ResultCoroutine2()
            {
                yield return null;
                yield return 1;
            }

            Debug.Log("test return result by coroutine: " + LockStepWorld.current.time);
            this.StartCoroutine_LS(TestCoroutine_LS_WithResult());
        }
        );

        keyInfos.Add(KeyCode.Alpha5, () =>
        {
            IEnumerator GlobalCoroutine()
            {
                Debug.Log("Test GlobalCoroutine, before WaitForSecond_LS(2): " + LockStepWorld.current.time);
                yield return new WaitForSecond_LS(2);
                Debug.Log("Test GlobalCoroutine, after WaitForSecond_LS(2): " + LockStepWorld.current.time);
            }

            Debug.Log("test global coroutine: " + LockStepWorld.current.time);
            LockStepWorld.current.StartCoroutine(GlobalCoroutine());
        }
        );
    }





    protected override void Update_LS()
    {
        keyInfos.All(a =>
        {
            if (a.Key == key)
            {
                key = KeyCode.None;
                a.Value();
            }

            return true;
        });

        if (printedUpdate) return;
        printedUpdate = true;

        Debug.Log("test Update_LS  " + updateOrder_ls);
    }

    protected override void LateUpdate_LS()
    {
        if (printedLateUpdate) return;
        printedLateUpdate = true;

        Debug.Log("test LateUpdate_LS  " + updateOrder_ls);
    }


    private void Update()
    {
        keyInfos.All(a =>
        {
            if (Input.GetKeyDown(a.Key))
            {
                key = a.Key;
            }

            return true;
        });
    }


    private void OnGUI()
    {
        GUILayout.Label("press key 1 to test timer");
        GUILayout.Label("press key 2 to test stop timer by callback result(false)");
        GUILayout.Label("press key 3 to test behaviour coroutine");
        GUILayout.Label("press key 4 to test result returned by coroutine");
        GUILayout.Label("press key 5 to test global coroutine");
    }



}
